﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Web.UI;
using System.Reflection;

namespace WebFormsBinder
{
    public class Binding<TEntity, TProperty, TControl> : AbstractBinding<TEntity>
    {
        PropertyInfo _property { get; set; }
        TControl _control { get; set; }
        IControlWrapper<TProperty, TControl> _explicitControlWrapper { get; set; }

        IControlWrapper<TProperty, TControl> ControlWrapperInUse
        {
            get
            {
                if (_explicitControlWrapper != null)
                    return _explicitControlWrapper;
                return ControlWrapperFinder.GetControlWrapper<TProperty, TControl>();
            }
        }

        public override PropertyInfo Property { get { return _property; } }

        internal override string JSValue { get { return ControlWrapperInUse.JSValue(_control); } }
        internal override string JSTypeValidationCondition { get { return ControlWrapperInUse.JSTypeValidationCondition(_control); } }
        internal override string JSElement { get { return ControlWrapperInUse.JSElement(_control); } }
        
        public Binding(Expression<Func<TEntity, TProperty>> property, TControl control)
        {
            _property = Util.GetPropertyInfo(property);
            _control = control;
        }

        public Binding<TEntity, TProperty, TControl> ControlWrapper(IControlWrapper<TProperty, TControl> controlWrapper)
        {
            _explicitControlWrapper = controlWrapper;
            return this;
        }

        public override void ToForm(TEntity entity)
        {
            ControlWrapperInUse.SetValue(_control, GetEntityValue(entity));
        }

        public override void ToEntity(TEntity entity)
        {
            TProperty val = ControlWrapperInUse.GetValue(_control);
            SetEntityValue(entity, val);
        }

        TProperty GetEntityValue(TEntity entity)
        {
            return (TProperty)_property.GetGetMethod().Invoke(entity, null);
        }

        void SetEntityValue(TEntity entity, TProperty value)
        {
            _property.GetSetMethod().Invoke(entity, new object[] { value });
        }
    }
}
